package engine.gameObject.terrain;

import static engine.util.vbo.VBO.*;

import java.nio.IntBuffer;

import org.lwjgl.BufferUtils;

/**
 * 
 * ________________
 *     |     |     
 *  1  |  2	 |  3
 * ____|_____|_____
 *     |     |
 *  4  |  5  |  6
 * ____|_____|_____
 *     |     |
 *  7  |  8  |  9
 * ____|_____|_____
 * @author richard
 *
 */
public class IndiciesCreator {
	
	private static int lastLength;
	
	private IndiciesCreator() {
		
	}
	
	private static void getIndicies2(IntBuffer buffer, int start, int end, int step, int detailAreaSize) {
		for(int i = start; i < end; i += 2 * step) {
			buffer.put((detailAreaSize + 1) * detailAreaSize + i);
			buffer.put((detailAreaSize + 1) * (detailAreaSize - step) + i + step);
			buffer.put((detailAreaSize + 1) * detailAreaSize + i + 2 * step);
			
			buffer.put((detailAreaSize + 1) * (detailAreaSize - step) + i);
			buffer.put((detailAreaSize + 1) * (detailAreaSize - step) + i + step);
			buffer.put((detailAreaSize + 1) * detailAreaSize + i);
			
			buffer.put((detailAreaSize + 1) * (detailAreaSize - step) + i + step);
			buffer.put((detailAreaSize + 1) * (detailAreaSize - step) + i + 2 * step);
			buffer.put((detailAreaSize + 1) * detailAreaSize + i + 2 * step);
		}
	}
	
	private static void getIndicies4(IntBuffer buffer, int start, int end, int step, int detailAreaSize) {
		for(int i = start; i < end; i += 2 * step) {
			buffer.put(i * (detailAreaSize + 1));
			buffer.put((i + step) * (detailAreaSize + 1) + step);
			buffer.put((i + 2 * step) * (detailAreaSize + 1));
			
			buffer.put(i * (detailAreaSize + 1));
			buffer.put(i * (detailAreaSize + 1) + step);
			buffer.put((i + step) * (detailAreaSize + 1) + step);
			
			buffer.put((i + 2 * step) * (detailAreaSize + 1));
			buffer.put((i + step) * (detailAreaSize + 1) + step);
			buffer.put((i + 2 * step) * (detailAreaSize + 1) + step);
		}
	}

	private static void getIndicies5(IntBuffer buffer, int startX, int startZ, int endX, int endZ, int step, int detailAreaSize) {
		for(int x = startX; x < endX; x += step) {
			for(int z = startZ; z < endZ; z += step) {
				buffer.put(z * (detailAreaSize + 1) + x);
				buffer.put(z * (detailAreaSize + 1) + x + step);
				buffer.put((z + step) * (detailAreaSize + 1) + x);
				
				buffer.put((z + step) * (detailAreaSize + 1) + x);
				buffer.put(z * (detailAreaSize + 1) + x + step);
				buffer.put((z + step) * (detailAreaSize + 1) + x + step);
			}
		}
	}
	
	private static void getIndicies6(IntBuffer buffer, int start, int end, int step, int detailAreaSize) {
		for(int i = start; i < end; i += 2 * step) {
			buffer.put(detailAreaSize + i * (detailAreaSize + 1));
			buffer.put(detailAreaSize + (i + 2 * step) * (detailAreaSize + 1));
			buffer.put((detailAreaSize - step) + (i + step) * (detailAreaSize + 1));
			
			buffer.put(detailAreaSize + (i + 2 * step) * (detailAreaSize + 1) - step);
			buffer.put((detailAreaSize - step) + (i + step) * (detailAreaSize + 1));
			buffer.put(detailAreaSize + (i + 2 * step) * (detailAreaSize + 1));
			
			buffer.put((detailAreaSize - step) + (i + step) * (detailAreaSize + 1));
			buffer.put(detailAreaSize + i * (detailAreaSize + 1) - step);
			buffer.put(detailAreaSize + i * (detailAreaSize + 1));
		}
	}
	
	private static void getIndicies8(IntBuffer buffer, int start, int end, int step, int detailAreaSize) {
		for(int i = start; i < end; i += 2 * step) {
			buffer.put(i);
			buffer.put(i + 2 * step);
			buffer.put((detailAreaSize + 1) * step + i + step);
			
			buffer.put(i);
			buffer.put((detailAreaSize + 1) * step + i + step);
			buffer.put((detailAreaSize + 1) * step + i);
			
			buffer.put((detailAreaSize + 1) * step + i + step);
			buffer.put(i + 2 * step);
			buffer.put((detailAreaSize + 1) * step + i + 2 * step);
		}
	}
	
	public static int getIndicies1(int step, int detailAreaSize) {
		IntBuffer buffer = BufferUtils.createIntBuffer(detailAreaSize / step * detailAreaSize / step * 6 - detailAreaSize / step * 3);
			
		getIndicies5(buffer, step, 0, detailAreaSize, detailAreaSize - step, step, detailAreaSize);
		
		getIndicies2(buffer, 2 * step, detailAreaSize, step, detailAreaSize);
		
		getIndicies4(buffer, 0, detailAreaSize - 2 * step, step, detailAreaSize);
		
		buffer.put((detailAreaSize + 1) * detailAreaSize);
		buffer.put((detailAreaSize + 1) * (detailAreaSize - 2 * step));
		buffer.put((detailAreaSize + 1) * (detailAreaSize - step) + step);
		
		buffer.put((detailAreaSize + 1) * (detailAreaSize - 2 * step));
		buffer.put((detailAreaSize + 1) * (detailAreaSize - 2 * step) + step);
		buffer.put((detailAreaSize + 1) * (detailAreaSize - step) + step);
		
		buffer.put((detailAreaSize + 1) * detailAreaSize);
		buffer.put((detailAreaSize + 1) * (detailAreaSize - step) + step);
		buffer.put((detailAreaSize + 1) * detailAreaSize + 2 * step);
		
		buffer.put((detailAreaSize + 1) * (detailAreaSize - step) + step);
		buffer.put((detailAreaSize + 1) * (detailAreaSize - step) + 2 * step);
		buffer.put((detailAreaSize + 1) * detailAreaSize + 2 * step);
		
		buffer.rewind();
		
		lastLength = buffer.capacity();
		
		return getBuffer(buffer);
	}
	
	public static int getIndicies2(int step, int detailAreaSize) {
		IntBuffer buffer = BufferUtils.createIntBuffer(detailAreaSize / step * detailAreaSize / step * 6 - detailAreaSize / step / 2 * 3);
		
		getIndicies5(buffer, 0, 0, detailAreaSize, detailAreaSize - step, step, detailAreaSize);
		
		getIndicies2(buffer, 0, detailAreaSize, step, detailAreaSize);
		
		buffer.rewind();
		
		lastLength = buffer.capacity();
		
		return getBuffer(buffer);
	}
	
	public static int getIndicies3(int step, int detailAreaSize) {
		IntBuffer buffer = BufferUtils.createIntBuffer(detailAreaSize / step * detailAreaSize / step * 6 - detailAreaSize / step * 3);
		
		getIndicies5(buffer, 0, 0, detailAreaSize - step, detailAreaSize - step, step, detailAreaSize);
		
		getIndicies2(buffer, 0, detailAreaSize - 2 * step, step, detailAreaSize);
		
		getIndicies6(buffer, 0, detailAreaSize - 2 * step, step, detailAreaSize);
		
		buffer.put((detailAreaSize + 1) * (detailAreaSize + 1 - step) - 1 - step);
		buffer.put((detailAreaSize + 1) * (detailAreaSize + 1 - 2 * step) - 1);
		buffer.put((detailAreaSize + 1) * (detailAreaSize + 1) - 1);
		
		buffer.put((detailAreaSize + 1) * (detailAreaSize + 1 - step) - 1 - step);
		buffer.put((detailAreaSize + 1) * (detailAreaSize + 1 - 2 * step) - 1 - step);
		buffer.put((detailAreaSize + 1) * (detailAreaSize + 1 - 2 * step) - 1);
		
		buffer.put((detailAreaSize + 1) * (detailAreaSize + 1) - 1 - 2 * step);
		buffer.put((detailAreaSize + 1) * (detailAreaSize + 1 - step) - 1 - step);
		buffer.put((detailAreaSize + 1) * (detailAreaSize + 1) - 1);
		
		buffer.put((detailAreaSize + 1) * (detailAreaSize + 1) - 1 - 2 * step);
		buffer.put((detailAreaSize + 1) * (detailAreaSize + 1 - step) - 1 - 2 * step);
		buffer.put((detailAreaSize + 1) * (detailAreaSize + 1 - step) - 1 - step);
		
		buffer.rewind();
		
		lastLength = buffer.capacity();
		
		return getBuffer(buffer);
	}
	
	public static int getIndicies4(int step, int detailAreaSize) {
		IntBuffer buffer = BufferUtils.createIntBuffer(detailAreaSize / step * detailAreaSize / step * 6 - detailAreaSize / step / 2 * 3);
		
		getIndicies5(buffer, step, 0, detailAreaSize, detailAreaSize, step, detailAreaSize);
		
		getIndicies4(buffer, 0, detailAreaSize, step, detailAreaSize);
		
		buffer.rewind();
		
		lastLength = buffer.capacity();
		
		return getBuffer(buffer);
	}
	
	public static int getIndicies5(int step, int detailAreaSize) {
		IntBuffer buffer = BufferUtils.createIntBuffer(detailAreaSize / step * detailAreaSize / step * 6);
		
		getIndicies5(buffer, 0, 0, detailAreaSize, detailAreaSize, step, detailAreaSize);
		buffer.rewind();
		
		lastLength = buffer.capacity();
		
		return getBuffer(buffer);
	}
	
	public static int getIndicies6(int step, int detailAreaSize) {
		IntBuffer buffer = BufferUtils.createIntBuffer(detailAreaSize / step * detailAreaSize / step * 6 - detailAreaSize / step / 2 * 3);
		
		getIndicies5(buffer, 0, 0, detailAreaSize - step, detailAreaSize, step, detailAreaSize);
		
		getIndicies6(buffer, 0, detailAreaSize, step, detailAreaSize);
		
		buffer.rewind();
		
		lastLength = buffer.capacity();
		
		return getBuffer(buffer);
	}
	
	public static int getIndicies7(int step, int detailAreaSize) {
		IntBuffer buffer = BufferUtils.createIntBuffer(detailAreaSize / step * detailAreaSize / step * 6 - detailAreaSize / step * 3);
		
		getIndicies5(buffer, step, step, detailAreaSize, detailAreaSize, step, detailAreaSize);
		
		getIndicies4(buffer, 2 * step, detailAreaSize, step, detailAreaSize);
		
		getIndicies8(buffer, 2 * step, detailAreaSize, step, detailAreaSize);
		
		buffer.put(0);
		buffer.put(2 * step);
		buffer.put((detailAreaSize + 1) * step + step);
		
		buffer.put((detailAreaSize + 1) * step + step);
		buffer.put(2 * step);
		buffer.put((detailAreaSize + 1) * step + 2 * step);
		
		buffer.put((detailAreaSize + 1) * 2 * step);
		buffer.put(0);
		buffer.put((detailAreaSize + 1) * step + step);
		
		buffer.put((detailAreaSize + 1) * 2 * step);
		buffer.put((detailAreaSize + 1) * step + step);
		buffer.put((detailAreaSize + 1) * 2 * step + step);
		
		buffer.rewind();
		
		lastLength = buffer.capacity();
		
		return getBuffer(buffer);
	}
	
	public static int getIndicies8(int step, int detailAreaSize) {
		IntBuffer buffer = BufferUtils.createIntBuffer(detailAreaSize / step * detailAreaSize / step * 6 - detailAreaSize / step / 2 * 3);
		
		getIndicies5(buffer, 0, step, detailAreaSize, detailAreaSize, step, detailAreaSize);
		
		getIndicies8(buffer, 0, detailAreaSize, step, detailAreaSize);
		
		buffer.rewind();
		
		lastLength = buffer.capacity();
		
		return getBuffer(buffer);
	}
	
	public static int getIndicies9(int step, int detailAreaSize) {
		IntBuffer buffer = BufferUtils.createIntBuffer(detailAreaSize / step * detailAreaSize / step * 6 - detailAreaSize / step * 3);
		
		getIndicies5(buffer, 0, step, detailAreaSize - step, detailAreaSize, step,detailAreaSize);
		
		getIndicies6(buffer, 2 * step, detailAreaSize, step, detailAreaSize);
		
		getIndicies8(buffer, 0, detailAreaSize - 2 * step, step, detailAreaSize);
		
		buffer.put(detailAreaSize);
		buffer.put((detailAreaSize + 1) * (step + 1) - 1 - step);
		buffer.put(detailAreaSize - 2 * step);
		
		buffer.put((detailAreaSize + 1) * (step + 1) - 1 - 2 * step);
		buffer.put(detailAreaSize - 2 * step);
		buffer.put((detailAreaSize + 1) * (step + 1) - 1 - step);
		
		buffer.put((detailAreaSize + 1) * (2 * step + 1) - 1);
		buffer.put((detailAreaSize + 1) * (step + 1) - 1 - step);
		buffer.put(detailAreaSize);
		
		buffer.put((detailAreaSize + 1) * (2 * step + 1) - 1 - step);
		buffer.put((detailAreaSize + 1) * (step + 1) - 1 - step);
		buffer.put((detailAreaSize + 1) * (2 * step + 1) - 1);
		
		buffer.rewind();
		
		lastLength = buffer.capacity();
		
		return getBuffer(buffer);
	}
	
	private static int getBuffer(IntBuffer buffer) {
		int index = glGenBuffers();
		glBindElementBuffer(index);
		glBufferElementData(index, buffer);
		glBindBuffer(0);
		
		buffer.clear();
		
		return index;
	}
	
	public static int getLastLength() {
		return lastLength;
	}
}
